home *** CD-ROM | disk | FTP | other *** search
/ Collection of Tools & Utilities / Collection of Tools and Utilities.iso / edit / elv18src.zip / elvprsv.c < prev    next >
C/C++ Source or Header  |  1994-01-10  |  8KB  |  330 lines

  1. /* elvprsv.c */
  2.  
  3. /* Author:
  4.  *    Steve Kirkendall
  5.  *    14407 SW Teal Blvd. #C
  6.  *    Beaverton, OR 97005
  7.  *    kirkenda@cs.pdx.edu
  8.  */
  9.  
  10.  
  11. /* This file contains the portable sources for the "elvprsv" program.
  12.  * "Elvprsv" is run by Elvis when Elvis is about to die.  It is also
  13.  * run when the computer boots up.  It is not intended to be run directly
  14.  * by the user, ever.
  15.  *
  16.  * Basically, this program does the following four things:
  17.  *    - It extracts the text from the temporary file, and places the text in
  18.  *    a file in the /usr/preserve directory.
  19.  *    - It adds a line to the /usr/preserve/Index file, describing the file
  20.  *    that it just preserved.
  21.  *    - It removes the temporary file.
  22.  *    -    It sends mail to the owner of the file, saying that the file was
  23.  *    preserved, and how it can be recovered.
  24.  *
  25.  * The /usr/preserve/Index file is a log file that contains one line for each
  26.  * file that has ever been preserved.  Each line of this file describes one
  27.  * preserved file.  The first word on the line is the name of the file that
  28.  * contains the preserved text.  The second word is the full pathname of the
  29.  * file that was being edited; for anonymous buffers, this is the directory
  30.  * name plus "/foo".
  31.  *
  32.  * If elvprsv's first argument (after the command name) starts with a hyphen,
  33.  * then the characters after the hyphen are used as a description of when
  34.  * the editor went away.  This is optional.
  35.  *
  36.  * The remaining arguments are all the names of temporary files that are
  37.  * to be preserved.  For example, on a UNIX system, the /etc/rc file might
  38.  * invoke it this way:
  39.  *
  40.  *    elvprsv "-the system went down" /tmp/elv_*.*
  41.  *
  42.  * This file contains only the portable parts of the preserve program.
  43.  * It must #include a system-specific file.  The system-specific file is
  44.  * expected to define the following functions:
  45.  *
  46.  *    char *ownername(char *filename)    - returns name of person who owns file
  47.  *
  48.  *    void mail(char *user, char *name, char *when, char *tmp)
  49.  *                    - tell user that file was preserved
  50.  */
  51.  
  52. #include <stdio.h>
  53. #include "config.h"
  54. #include "vi.h"
  55.  
  56. /* We include ctype.c here (instead of including just ctype.h and linking
  57.  * with ctype.o) because on some systems ctype.o will have been compiled in
  58.  * "large model" and the elvprsv program is to be compiled in "small model" 
  59.  * You can't mix models.  By including ctype.c here, we can avoid linking
  60.  * with ctype.o.
  61.  */
  62. #include "ctype.c"
  63.  
  64. void preserve P_((char *, char *));
  65. void main P_((int, char **));
  66.  
  67. #if AMIGA
  68. BLK tmpblk;
  69. # include "amiwild.c"
  70. # include "amiprsv.c"
  71. #endif
  72.  
  73. #if OSK
  74. # undef sprintf
  75. #endif
  76.  
  77. #if ANY_UNIX || OSK
  78. # include "prsvunix.c"
  79. #endif
  80.  
  81. #if MSDOS || TOS || OS2
  82. # include "prsvdos.c"
  83. # define WILDCARD_NO_MAIN
  84. # include "wildcard.c"
  85. #endif
  86.  
  87.  
  88. BLK    buf;
  89. BLK    hdr;
  90. BLK    name;
  91. int    rewrite_now;    /* boolean: should we send text directly to orig file? */
  92.  
  93.  
  94.  
  95. /* This function preserves a single file, and announces its success/failure
  96.  * via an e-mail message.
  97.  */
  98. void preserve(tname, when)
  99.     char    *tname;        /* name of a temp file to be preserved */
  100.     char    *when;        /* description of when the editor died */
  101. {
  102.     int    infd;        /* fd used for reading from the temp file */
  103.     FILE    *outfp;        /* fp used for writing to the recovery file */
  104.     FILE    *index;        /* fp used for appending to index file */
  105.     char    outname[100];    /* the name of the recovery file */
  106.     char    *user;        /* name of the owner of the temp file */
  107. #if AMIGA
  108.     char    *prsvdir;
  109. #endif
  110.     int    i;
  111.  
  112.     /* open the temp file */
  113.     infd = open(tname, O_RDONLY|O_BINARY);
  114.     if (infd < 0)
  115.     {
  116.         /* if we can't open the file, then we should assume that
  117.          * the filename contains wildcard characters that weren't
  118.          * expanded... and also assume that they weren't expanded
  119.          * because there are no files that need to be preserved.
  120.          * THEREFORE... we should silently ignore it.
  121.          * (Or loudly ignore it if the user was using -R)
  122.          */
  123.         if (rewrite_now)
  124.         {
  125.             perror(tname);
  126.         }
  127.         return;
  128.     }
  129.  
  130.     /* read the header and name from the file */
  131.     if (read(infd, hdr.c, BLKSIZE) != BLKSIZE
  132.      || read(infd, name.c, BLKSIZE) != BLKSIZE)
  133.     {
  134.         /* something wrong with the file - sorry */
  135.         fprintf(stderr, "%s: truncated header blocks\n", tname);
  136.         close(infd);
  137.         return;
  138.     }
  139.  
  140.     /* If the filename block contains an empty string, then Elvis was
  141.      * only keeping the temp file around because it contained some text
  142.      * that was needed for a named cut buffer.  The user doesn't care
  143.      * about that kind of temp file, so we should silently delete it.
  144.      */
  145.     if (name.c[0] == '\0' && name.c[1] == '\177')
  146.     {
  147.         close(infd);
  148.         unlink(tname);
  149.         return;
  150.     }
  151.  
  152.     /* If there are no text blocks in the file, then we must've never
  153.      * really started editing.  Discard the file.
  154.      */
  155.     if (hdr.n[1] == 0)
  156.     {
  157.         close(infd);
  158.         unlink(tname);
  159.         return;
  160.     }
  161.  
  162.     if (rewrite_now)
  163.     {
  164.         /* we don't need to open the index file */
  165.         index = (FILE *)0;
  166.  
  167.         /* make sure we can read every block! */
  168.         for (i = 1; i < MAXBLKS && hdr.n[i]; i++)
  169.         {
  170.             lseek(infd, (long)hdr.n[i] * (long)BLKSIZE, 0);
  171.             if (read(infd, buf.c, BLKSIZE) != BLKSIZE
  172.              || buf.c[0] == '\0')
  173.             {
  174.                 /* messed up header */
  175.                 fprintf(stderr, "%s: unrecoverable -- header trashed\n", name.c);
  176.                 close(infd);
  177.                 return;
  178.             }
  179.         }
  180.  
  181.         /* open the user's file for writing */
  182.         outfp = fopen(name.c, "w");
  183.         if (!outfp)
  184.         {
  185.             perror(name.c);
  186.             close(infd);
  187.             return;
  188.         }
  189.     }
  190.     else
  191.     {
  192.         /* open/create the index file */
  193.         index = fopen(PRSVINDEX, "a");
  194.         if (!index)
  195.         {
  196.             perror(PRSVINDEX);
  197.             mail(ownername(tname), name.c, when, tname);
  198.             exit(2);
  199.         }
  200.  
  201.         /* should be at the end of the file already, but MAKE SURE */
  202.         fseek(index, 0L, 2);
  203.  
  204.         /* create the recovery file in the PRESVDIR directory */
  205. #if AMIGA
  206.         prsvdir = &PRSVDIR[strlen(PRSVDIR) - 1];
  207.         if (*prsvdir == '/' || *prsvdir == ':')
  208.         {
  209.             sprintf(outname, "%sp%ld", PRSVDIR, ftell(index));
  210.         }
  211.         else
  212. #endif
  213.         sprintf(outname, "%s%cp%ld", PRSVDIR, SLASH, ftell(index));
  214.         outfp = fopen(outname, "w");
  215.         if (!outfp)
  216.         {
  217.             perror(outname);
  218.             close(infd);
  219.             fclose(index);
  220.             mail(ownername(tname), name.c, when, tname);
  221.             return;
  222.         }
  223.     }
  224.  
  225.     /* write the text of the file out to the recovery file */
  226.     for (i = 1; i < MAXBLKS && hdr.n[i]; i++)
  227.     {
  228.         lseek(infd, (long)hdr.n[i] * (long)BLKSIZE, 0);
  229.         if (read(infd, buf.c, BLKSIZE) != BLKSIZE
  230.          || buf.c[0] == '\0')
  231.         {
  232.             /* messed up header */
  233.             fprintf(stderr, "%s: unrecoverable -- header trashed\n", name.c);
  234.             fclose(outfp);
  235.             close(infd);
  236.             if (index)
  237.             {
  238.                 fclose(index);
  239.             }
  240.             unlink(outname);
  241.             return;
  242.         }
  243.         fputs(buf.c, outfp);
  244.     }
  245.  
  246.     /* add a line to the index file */
  247.     if (index)
  248.     {
  249.         fprintf(index, "%s %s\n", outname, name.c);
  250.     }
  251.  
  252.     /* close everything */
  253.     close(infd);
  254.     fclose(outfp);
  255.     if (index)
  256.     {
  257.         fclose(index);
  258.     }
  259.  
  260.     /* Are we doing this due to something more frightening than just
  261.      * a ":preserve" command?
  262.      */
  263.     if (*when)
  264.     {
  265.         /* send a mail message */
  266.         mail(ownername(tname), name.c, when, (char *)0);
  267.  
  268.         /* remove the temp file -- the editor has died already */
  269.         unlink(tname);
  270.     }
  271. }
  272.  
  273. void main(argc, argv)
  274.     int    argc;
  275.     char    **argv;
  276. {
  277.     int    i;
  278.     char    *when = "the editor went away";
  279.  
  280. #ifdef __EMX__
  281.     _wildcard(&argc, &argv);
  282. #else
  283. # if MSDOS || TOS || OS2
  284.     /* expand any wildcards in the command line */
  285.     _ct_init("");
  286.     argv = wildexpand(&argc, argv);
  287. # endif
  288. #endif
  289.  
  290.     /* do we have a "-c", "-R", or "-when elvis died" argument? */
  291.     i = 1;
  292.     if (argc >= i + 1 && !strcmp(argv[i], "-R"))
  293.     {
  294.         rewrite_now = 1;
  295.         when = "";
  296.         i++;
  297. #if ANY_UNIX
  298.         setuid(geteuid());
  299. #endif
  300.     }
  301. #if OSK
  302.     else
  303.     {
  304.         setuid(0);
  305.     }
  306. #endif
  307.     if (argc >= i + 1 && argv[i][0] == '-')
  308.     {
  309.         when = argv[i] + 1;
  310.         i++;
  311.     }
  312.  
  313.     /* preserve everything we're supposed to */
  314.     while (i < argc)
  315.     {
  316.         char *p = argv[i] - 1;
  317.  
  318.         /* reconvert any converted spaces */
  319.         while (*++p)
  320.         {
  321.             if ((unsigned char)(*p) == SPACEHOLDER)
  322.             {
  323.                 *p = ' ';
  324.             }
  325.         }
  326.         preserve(argv[i], when);
  327.         i++;
  328.     }
  329. }
  330.